﻿using System;
using System.Collections.Generic;
using System.Windows.Automation;
using QuickUIT.Utilities;

namespace QuickUIT.Controls
{
    /// <summary>
    /// Represents a combo box control. 
    /// </summary>
    public class UIComboBox : UIBaseControl
    {
        /// <summary>
        /// Gets or sets the current value of the combo box if it supports arbitrary text values. 
        /// </summary>
        public new string Value
        {
            get { return base.Value; }
            set { SetValue(value); }
        }

        /// <summary>
        /// Gets the current expand/collapse state of the combo box.
        /// </summary>
        public new ExpandCollapseState ExpandCollapseState
        {
            get { return base.ExpandCollapseState.GetValueOrDefault(); }
        }

        /// <summary>
        /// Gets a value which indicates if the control allows more than one child element to be selected concurrently. 
        /// </summary>
        public new bool CanSelectMultiple
        {
            get { return base.CanSelectMultiple; }
        }

        /// <summary>
        /// Gets a value which indicates if the control requires at least one child element to be selected. 
        /// </summary>
        public new bool IsSelectionRequired
        {
            get { return base.IsSelectionRequired; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UIComboBox"/> class. 
        /// </summary>
        public UIComboBox() : base(ControlType.ComboBox)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UIComboBox"/> class.
        /// </summary>
        /// <param name="parent">The parent of this control.</param>
        public UIComboBox(UIBaseControl parent) : base(parent, ControlType.ComboBox)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UIComboBox"/> class.
        /// </summary>
        /// <param name="locator">The locator used to find the specific control.</param>
        public UIComboBox(string locator) : base(null, ControlType.ComboBox, locator)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UIComboBox"/> class.
        /// </summary>
        /// <param name="parent">The parent of this control.</param>
        /// <param name="locator">The locator used to find the specific control.</param>
        public UIComboBox(UIBaseControl parent, string locator) : base(parent, ControlType.ComboBox, locator)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UIComboBox"/> class.
        /// </summary>
        /// <param name="control">The underlying <see cref="AutomationElement"/> of the control.</param>
        public UIComboBox(AutomationElement control) : base(control, ControlType.ComboBox)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UIComboBox"/> class.
        /// </summary>
        /// <param name="parent">The parent of the control</param>
        /// <param name="control">The underlying <see cref="AutomationElement"/> of the control.</param>
        public UIComboBox(UIBaseControl parent, AutomationElement control) : base(parent, control, ControlType.ComboBox)
        {
        }

        /// <summary>
        /// Expands the combo box. 
        /// </summary>
        /// <exception cref="InvalidOperationException">The control pattern cannot be performed by the element.</exception>
        /// <exception cref="ElementNotAvailableException">The element is not available anymore.</exception>
        public new void Expand()
        {
            base.Expand();
        }

        /// <summary>
        /// Collapses the combo box. 
        /// </summary>
        /// <exception cref="InvalidOperationException">The control pattern cannot be performed by the element.</exception>
        /// <exception cref="ElementNotAvailableException">The element is not available anymore.</exception>
        public new void Collapse()
        {
            base.Collapse();
        }

        /// <summary>
        /// Selects an item from the combo box by name. 
        /// </summary>
        /// <param name="itemName">The name of the item to select from the combo box.</param>
        /// <exception cref="InvalidOperationException">The control pattern cannot be performed by the element.</exception>
        /// <exception cref="ElementNotAvailableException">The element is not available anymore.</exception>
        public void SelectItem(string itemName)
        {
            Expand();
            var criteria = new AutomationElementSearchCriteria();
            criteria.Add(new AutomationElementExactSearchCondition(AutomationElementIdentifiers.NameProperty, itemName));
            AutomationElement item = AutomationElementFinder.FindFirst(Control, criteria);
            while (item == null && !double.IsNaN(VerticalScrollPercent) && VerticalScrollPercent != ScrollPattern.NoScroll && VerticalScrollPercent != 100.0)
            {
                ScrollVertically(ScrollAmount.LargeIncrement);
                item = AutomationElementFinder.FindFirst(Control, criteria);
            }
            AutomationElementPatterns.ScrollIntoView(item);
            AutomationElementPatterns.Select(item);
            Collapse();
        }
        
        /// <summary>
        /// Gets the current selection for this combo box. 
        /// </summary>
        /// <returns>The <see cref="AutomationElement"/> of the current selected combo box item. Returns null if there is no selected item.</returns>
        /// <exception cref="InvalidOperationException">The control pattern cannot be performed by the element.</exception>
        /// <exception cref="ElementNotAvailableException">The element is not available anymore.</exception>
        public AutomationElement GetSelectedItem()
        {
            WaitForParentWindowToBeReady();
            var selection = AutomationElementPatterns.GetSelection(Control);
            return selection.Length == 0 ? null : selection[0];
        }

        /// <summary>
        /// Gets a collection of elements that represents the current selection for the combo box.
        /// </summary>
        /// <returns>A collection of selected elements.</returns>
        /// <exception cref="InvalidOperationException">The control pattern cannot be performed by the element.</exception>
        /// <exception cref="ElementNotAvailableException">The element is not available anymore.</exception>
        public new AutomationElement[] GetSelection()
        {
            return base.GetSelection(); 
        }
    }
}
